package com.java.base.jvm;


import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;


public class ReferenceTest {


    public SoftReference<Object> soft = new SoftReference<>(new Object());
    public WeakReference<Object> weak = new WeakReference<>(new Object());

    ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
    PhantomReference<Object> phantom = new PhantomReference<>(new Object(), referenceQueue);

    //-Xmx=64m --add-exports java.base/jdk.internal.ref=ALL-UNNAMED
    public static void main(String[] args) throws InterruptedException, ClassNotFoundException {
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(12);
        byteBuffer.put(1, (byte) 1);
        byte[] bb = new byte[11];
        byteBuffer.get(bb);
        System.out.println(bb[1]);
        System.out.println(System.identityHashCode(bb[1]));
        System.out.println(System.identityHashCode(byteBuffer.get(1)));

        ReferenceTest referenceTest = new ReferenceTest();
        printReference(referenceTest);

        byte[] byte1 = heap();

        System.out.println(byte1.length);
        printReference(referenceTest);
        System.gc();

        byte[] bytes = heap();
        printReference(referenceTest);

        System.out.println(bytes.length);

    }

    public static void printReference(ReferenceTest referenceTest) {
        System.out.println("===================");
        System.out.println(referenceTest.soft.get());
        System.out.println(referenceTest.weak.get());
        System.out.println(referenceTest.referenceQueue.poll());
        System.out.println(referenceTest.phantom.get());
    }


    public static byte[] heap() {
        byte[] bytes = null;
        for (int i = 0; i < 100; i++) {
            bytes = new byte[2 * 1024 * 1024];
            int j = i;
            cleaner(bytes, () -> {
                System.out.println("回收了bytes" + j);
            });
        }
        return bytes;
    }


    public static void cleaner(Object ob, Runnable thunk) {

        try {
            Class<?> clz = Class.forName("jdk.internal.ref.Cleaner");
            Method method = clz.getMethod("create", Object.class, Runnable.class);
            method.setAccessible(true);
            method.invoke(null, ob, thunk);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
